package cn.universal.plugins.protocolapi.backup.web;

import cn.universal.plugins.protocolapi.backup.model.Backup;
import cn.universal.plugins.protocolapi.backup.service.MagicBackupService;
import cn.universal.plugins.protocolapi.core.config.Constants;
import cn.universal.plugins.protocolapi.core.config.MagicConfiguration;
import cn.universal.plugins.protocolapi.core.model.Group;
import cn.universal.plugins.protocolapi.core.model.JsonBean;
import cn.universal.plugins.protocolapi.core.model.MagicEntity;
import cn.universal.plugins.protocolapi.core.service.MagicDynamicRegistry;
import cn.universal.plugins.protocolapi.core.web.MagicController;
import cn.universal.plugins.protocolapi.core.web.MagicExceptionHandler;
import cn.universal.plugins.protocolapi.utils.JsonUtils;
import cn.universal.plugins.protocolapi.utils.WebUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

public class MagicBackupController extends MagicController implements MagicExceptionHandler {

  private final MagicBackupService service;

  public MagicBackupController(MagicConfiguration configuration) {
    super(configuration);
    this.service = configuration.getMagicBackupService();
  }

  @GetMapping("/backups")
  @ResponseBody
  public JsonBean<List<Backup>> backups(Long timestamp) {
    if (service == null) {
      return new JsonBean<>(Collections.emptyList());
    }
    return new JsonBean<>(
        service.backupList(timestamp == null ? System.currentTimeMillis() : timestamp));
  }

  @GetMapping("/backup/{id}")
  @ResponseBody
  public JsonBean<List<Backup>> backups(@PathVariable("id") String id) {
    if (service == null || StringUtils.isBlank(id)) {
      return new JsonBean<>(Collections.emptyList());
    }
    return new JsonBean<>(service.backupById(id));
  }

  @PostMapping("/backup/rollback")
  @ResponseBody
  public JsonBean<Boolean> rollback(String id, Long timestamp) throws IOException {
    notNull(service, BACKUP_NOT_ENABLED);
    Backup backup = service.backupInfo(id, timestamp);
    if ("full".equals(id)) {
      service.doBackupAll("还原全量备份前，系统自动全量备份", WebUtils.currentUserName());
      configuration
          .getMagicAPIService()
          .upload(new ByteArrayInputStream(backup.getContent()), Constants.UPLOAD_MODE_FULL);
      return new JsonBean<>(true);
    }
    if (backup.getType().endsWith("-group")) {
      Group group = JsonUtils.readValue(backup.getContent(), Group.class);
      return new JsonBean<>(MagicConfiguration.getMagicResourceService().saveGroup(group));
    }
    MagicEntity entity =
        configuration.getMagicDynamicRegistries().stream()
            .map(MagicDynamicRegistry::getMagicResourceStorage)
            .filter(it -> it.folder().equals(backup.getType()))
            .map(it -> it.read(backup.getContent()))
            .findFirst()
            .orElse(null);
    if (entity != null) {
      return new JsonBean<>(MagicConfiguration.getMagicResourceService().saveFile(entity));
    }
    return new JsonBean<>(false);
  }

  @GetMapping("/backup")
  @ResponseBody
  public JsonBean<String> backup(Long timestamp, String id) {
    notNull(service, BACKUP_NOT_ENABLED);
    notBlank(id, PARAMETER_INVALID);
    notNull(timestamp, PARAMETER_INVALID);
    Backup backup = service.backupInfo(id, timestamp);
    MagicEntity entity = JsonUtils.readValue(backup.getContent(), MagicEntity.class);
    return new JsonBean<>(entity == null ? null : entity.getScript());
  }

  @PostMapping("/backup/full")
  @ResponseBody
  public JsonBean<Boolean> doBackup() throws IOException {
    notNull(service, BACKUP_NOT_ENABLED);
    service.doBackupAll("主动全量备份", WebUtils.currentUserName());
    return new JsonBean<>(true);
  }
}
